package coupon

import (
	"context"
	"encoding/json"
	"strconv"
	"strings"

	"mall/common/utils/pointy"
	"mall/service/backend/api/internal/logic/promotion/util"
	"mall/service/backend/api/internal/logic/utils"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/api/internal/utils/parse"
	enum "mall/service/backend/common/enum/promotion"
	"mall/service/backend/common/i18n"
	"mall/service/promotion/rpc/promotionclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetCouponTemplateListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetCouponTemplateListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCouponTemplateListLogic {
	return &GetCouponTemplateListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetCouponTemplateListLogic) GetCouponTemplateList(
	req *types.GetCouponTemplateListReq,
) (*types.GetCouponTemplateListResp, error) {
	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	orderBys := util.ParseSorterNew(req.Sorter)
	filterBys := util.ParseFilterNew(req.Filter, req.Type)

	var ids *string
	var search *string
	if req.Search != nil && len(strings.TrimSpace(*req.Search)) > 0 { // 前端可以搜名称或者ID
		reqSearch := strings.TrimSpace(*req.Search)
		if _, err := strconv.ParseInt(reqSearch, 10, 64); err == nil {
			ids = pointy.GetPointer(reqSearch)
		} else {
			search = pointy.GetPointer(strings.TrimSuffix(reqSearch, ","))
		}
	}
	var name *string
	if req.Name != nil && len(strings.TrimSpace(*req.Name)) > 0 {
		name = pointy.GetPointer(strings.TrimSpace(*req.Name))
	}
	var slug *string
	if req.Slug != nil && len(strings.TrimSpace(*req.Slug)) > 0 {
		slug = pointy.GetPointer(strings.TrimSpace(*req.Slug))
	}

	if req.Id != nil && *req.Id > 0 {
		ids = pointy.GetPointer(strconv.FormatInt(int64(*req.Id), 10))
	}

	data, err := l.svcCtx.PromotionRpc.BackendGetCouponTemlateList(l.ctx, &promotionclient.CouponTemlateListReq{
		Page:       page,
		PageSize:   pageSize,
		Ids:        ids,
		Name:       name,
		Slug:       slug,
		CouponType: req.CouponType,
		ScopeType:  req.ScopeType,
		Status:     req.Status,
		Search:     search,
		StartTime:  req.StartTime,
		EndTime:    req.EndTime,
		OrderBy:    orderBys,
		FilterBy:   filterBys,
		WithMeta:   req.WithMeta,
		WithMedia:  req.WithMedia,
	})
	if err != nil {
		return nil, err
	}

	resp := &types.GetCouponTemplateListResp{
		BaseDataInfo: types.BaseDataInfo{
			Success: true,
			Msg:     l.svcCtx.Trans.Trans(l.ctx, i18n.Success),
		},
		Data: types.GetCouponTemplateListInfo{
			BaseListInfo: types.BaseListInfo{
				Current:  page,
				PageSize: pageSize,
				Total:    data.GetTotal(),
			},
			StatusStatisticMap: data.StatusStatisticMap,
		},
	}

	for _, v := range data.List {
		var meta []*types.MetaInfo
		var media []*types.MediaInfo

		if len(v.Meta) > 0 {
			for _, m := range v.Meta {
				meta = append(meta, &types.MetaInfo{
					Id:    m.Id,
					Key:   m.Key,
					Value: m.Value,
				})
			}
		}

		if len(v.Media) > 0 {
			for _, m := range v.Media {
				var url string
				if m.Url != nil && len(*m.Url) > 0 {
					url = *m.Url
				}
				if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
					url = *m.Uri
				}
				filename, mimeType, metaData := utils.ParseMetaData(m.MetaData)
				media = append(media, &types.MediaInfo{
					Uid:       m.Uid,
					Id:        m.Id,
					Thumbnail: m.Thumbnail,
					Order:     m.Order,
					Url:       pointy.GetPointer(url),
					Name:      pointy.GetPointer(filename),
					MimeType:  pointy.GetPointer(mimeType),
					AltText:   m.AltText,
					MetaData:  pointy.GetPointer(metaData),
				})
			}
		}

		var mustBind bool
		var canBind bool
		if v.Step != nil && v.ScopeType != nil && uint8(*v.ScopeType) > enum.PromotionScopeAll {
			switch uint8(*v.Step) {
			case enum.PromotionActivityStepBasic:
				mustBind = true
				canBind = true
			case enum.PromotionActivityStepMain, enum.PromotionActivityStepGift:
				canBind = true
			}
		}
		option := util.GetOptionByStatus(v.Status, mustBind, canBind)

		var regions []*types.TreeNode
		if v.Regions != nil {
			if err := json.Unmarshal([]byte(*v.Regions), &regions); err != nil {
				logx.Errorw("GetCouponTemplateList Regions json.Unmarshal err", logx.Field("detail", err.Error()))
			}
		}

		resp.Data.List = append(resp.Data.List, &types.CouponTemplateInfo{
			BaseIDInfo: types.BaseIDInfo{
				Id:         v.Id,
				CreatedAt:  v.CreatedAt,
				UpdatedAt:  v.UpdatedAt,
				DeletedAt:  v.DeletedAt,
				CanAccept:  option.CanAccept,
				CanReject:  option.CanReject,
				CanRemove:  option.CanRemove,
				CanRestore: option.CanRestore,
			},
			Name:     v.Name,
			Slug:     v.Slug,
			DescHtml: v.Desc,
			Desc:     v.FilteredDesc,
			Status:   v.Status,
			Sort:     v.Sort,
			Count:    v.Count,
			Meta:     meta,
			Media:    media,

			MemberRestriction: v.MemberRestriction,
			CouponType:        v.CouponType,
			MutexType:         v.MutexType,
			ScopeType:         v.ScopeType,
			GemPrice:          v.GemPrice,
			Condition:         v.Condition,
			ConditionValue:    v.ConditionValue,
			DiscountMode:      v.DiscountMode,
			DiscountValue:     v.DiscountValue,
			Regions:           regions,
			PerLimit:          v.PerLimit,
			ApplyStartedAt:    v.ApplyStartedAt,
			ApplyEndedAt:      v.ApplyEndedAt,
			ExpireMode:        v.ExpireMode,
			ExpireValue:       v.ExpireValue,
			StartedAt:         v.StartedAt,
			EndedAt:           v.EndedAt,
			MustBind:          option.MustBind,
			CanBind:           option.CanBind,
		})
	}

	return resp, nil
}
